<?php
/**
 * APIDatabaseAdminTest
 */
class APIDatabaseAdminTest extends APIWebServiceTest
{
    public static function setUpBeforeClass () {
        self::_setUpBeforeClass("APIDatabaseAdminTest");
    }
    public static function tearDownAfterClass () {
        self::_tearDownAfterClass();
    }

    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    public function setUp () {}

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    public function tearDown () {}

    /**
     * @covers API\DatabaseAdmin::createDatabase
     */
    public function testCreateDatabase()
    {
        global $context;
        $admin = $context->sessionObject('administration', array('class' => 'App\\Administration'));
        $testdb = $context->database('testdb');
        $testdb->drop_table('test1');
        $admin->requestDropDatabase('testdb');

        $request  = array('db_name'=>'testdb');
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/createDatabase', $request, $response);
        # $response = { "success": true }
        $this->assertTrue(isset($response['success']),                  "createDatabase: success");

        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/createDatabase', $request, $response);
        # $response = {
        #     "success": false,
        #     "code": 0,
        #     "message": "There is already a database by the name of 'testdb'",
        # }
        $this->assertTrue(isset($response['success']),                 "createDatabase: success is set");
        $this->assertFalse($response['success'],                       "createDatabase: not success");
        $this->assertTrue(isset($response['message']),                 "createDatabase: message is set");
        $this->assertTrue(strpos($response['message'],'There is already a database by the name of') !== false, "createDatabase: message is correct");
    }

    /**
     * @covers API\DatabaseAdmin::listDatabaseObjects
     * @depends testCreateDatabase
     */
    public function testListDatabaseObjects()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('GET', '/service/databaseAdmin/listDatabaseObjects', $request, $response);
        # $response = {"success":true,
        #              "db_name":"main",
        #              "db_id":"6",
        #              "databases":[{"db_id":"6","db_name":"main","db_label":"Main User-Defined Database"},
        #                           {"db_id":"7","db_name":"app","db_label":"Application Database"},
        #                           {"db_id":"8","db_name":"reference","db_label":"Reference Database"}],
        #              "table_name":null,
        #              "table_id":null,
        #              "tables":[],
        #              "columns":[]}
        $this->assertTrue(isset($response['success']),                  "listDatabaseObjects: success");
        $this->assertTrue(isset($response['databases']),                "listDatabaseObjects: has list of databases");
        $num_databases = count($response['databases']);
        $this->assertTrue($num_databases > 0,                           "listDatabaseObjects: databases list is not empty ($num_databases)");
        $this->assertTrue(isset($response['databases'][0]['db_name']),  "listDatabaseObjects: first database has a db_name");
        $this->assertTrue(isset($response['databases'][0]['db_label']), "listDatabaseObjects: first database has a db_label");
        $first_db_name = $response['databases'][0]['db_name'];
        $this->assertEquals($response['db_name'], $first_db_name,       "listDatabaseObjects: starts with first database ($first_db_name)");
    }

    /**
     * @covers API\DatabaseAdmin::listDatabases
     * @depends testListDatabaseObjects
     */
    public function testListDatabases()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('GET', '/service/databaseAdmin/listDatabases', $request, $response);
        $this->assertTrue(isset($response['success']),                  "listDatabases: success is set");
        #$this->assertTrue($response['success'],                         "listDatabases: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::getDatabaseInfo
     * @depends testListDatabases
     */
    public function testGetDatabaseInfo()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('GET', '/service/databaseAdmin/getDatabaseInfo', $request, $response);
        $this->assertTrue(isset($response['success']),                  "getDatabaseInfo: success is set");
        #$this->assertTrue($response['success'],                         "getDatabaseInfo: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::setDatabaseInfo
     * @depends testGetDatabaseInfo
     */
    public function testSetDatabaseInfo()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/setDatabaseInfo', $request, $response);
        $this->assertTrue(isset($response['success']),                  "setDatabaseInfo: success is set");
        #$this->assertTrue($response['success'],                         "setDatabaseInfo: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::_make_canonical_table_def
     */
    public function testMakeCanonicalTableDef()
    {
        global $context;
        $testdb = $context->database('testdb');

        $table_def  = json_decode('{"table_name":"test1","columns":"a,b,c"}', true);
        $testdb->_make_canonical_table_def($table_def);
        $exp_table_def_json = <<<EOF
{
  "table_name":"test1",
  "columns":["a","b","c"],
  "column":{
    "a":{"column_name":"a","column_type":"string","max_length":80},
    "b":{"column_name":"b","column_type":"string","max_length":80},
    "c":{"column_name":"c","column_type":"string","max_length":80}
  }
}
EOF;
        $exp_table_def  = json_decode($exp_table_def_json, true);
        $this->assertDeeply($exp_table_def, $table_def, "Line#".__LINE__." _make_canonical_table_def() : table_def", false);
    }

    /**
     * @covers API\DatabaseAdmin::createTable
     * @depends testSetDatabaseInfo
     */
    public function testCreateTable()
    {
        global $context;
        $testdb = $context->database('testdb');
        $response_success_only = json_decode('{"success":true}',true);
        $response_failure_only = json_decode('{"success":false}',true);

        #$request_json = '{"db_name":"testdb"}';
        #$request  = json_decode($request_json, true);
        #$response = array();
        #$this->_callWebService('POST', "/service/databaseAdmin/createTable", $request, $response);
        #$this->assertDeeply($response_failure_only, $response, "Line#".__LINE__." POST /service/databaseAdmin/createTable response", false);

        #$request_json = '{"table":"test1"}';
        #$request  = json_decode($request_json, true);
        #$response = array();
        #$this->_callWebService('POST', "/service/databaseAdmin/createTable", $request, $response);
        #$this->assertDeeply($response_failure_only, $response, "Line#".__LINE__." POST /service/databaseAdmin/createTable response", false);

        $request_json = '{"db_name":"testdb", "table_name":"test1", "columns":"a,b,c"}';
        $request  = json_decode($request_json, true);
        $response = array();
        $this->_callWebService('POST', "/service/databaseAdmin/createTable", $request, $response);
        $this->assertDeeply($response_success_only, $response, "Line#".__LINE__." POST /service/databaseAdmin/createTable response", false);
        $table_def = $testdb->get_table_def("test1");
        $exp_table_def  = json_decode('{"table_name":"test1","columns":["a","b","c"],"phys_columns":["a","b","c"],"column":{"a":{"column_name":"a","column_type":"string","max_length":80}}}', true);
        $this->assertDeeply($exp_table_def, $table_def, "Line#".__LINE__." POST /service/databaseAdmin/createTable table_def", false);

#        $expected_response_json = <<<EOF
#{
#    "success": true
#}
#EOF;
#        $expected_response  = json_decode($expected_response_json, true);
#        $this->assertDeeply($expected_response, $response, "Line#".__LINE__." POST /object/app/email (array of objects) response");
    }

    /**
     * @covers API\DatabaseAdmin::listTables
     * @depends testCreateTable
     */
    public function testListTables()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('GET', '/service/databaseAdmin/listTables', $request, $response);
        $this->assertTrue(isset($response['success']),                  "listTables: success is set");
        #$this->assertTrue($response['success'],                         "listTables: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::getTableInfo
     * @depends testListTables
     */
    public function testGetTableInfo()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('GET', '/service/databaseAdmin/getTableInfo', $request, $response);
        $this->assertTrue(isset($response['success']),                  "getTableInfo: success is set");
        #$this->assertTrue($response['success'],                         "getTableInfo: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::renameTable
     * @depends testGetTableInfo
     */
    public function testRenameTable()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/renameTable', $request, $response);
        $this->assertTrue(isset($response['success']),                  "renameTable: success is set");
        ##$this->assertTrue($response['success'],                         "renameTable: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::alterTable
     * @depends testRenameTable
     */
    public function testAlterTable()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/alterTable', $request, $response);
        $this->assertTrue(isset($response['success']),                  "alterTable: success is set");
        #$this->assertTrue($response['success'],                         "alterTable: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::exportTable
     * @depends testAlterTable
     */
    public function testExportTable()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('GET', '/service/databaseAdmin/exportTable', $request, $response);
        $this->assertTrue(isset($response['success']),                  "exportTable: success is set");
        #$this->assertTrue($response['success'],                         "exportTable: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::importTable
     * @depends testExportTable
     */
    public function testImportTable()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/importTable', $request, $response);
        $this->assertTrue(isset($response['success']),                  "importTable: success is set");
        #$this->assertTrue($response['success'],                         "importTable: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::defineRelatedTable
     * @depends testImportTable
     */
    public function testDefineRelatedTable()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/defineRelatedTable', $request, $response);
        $this->assertTrue(isset($response['success']),                  "defineRelatedTable: success is set");
        #$this->assertTrue($response['success'],                         "defineRelatedTable: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::defineDisplayColumn
     * @depends testDefineRelatedTable
     */
    public function testDefineDisplayColumn()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/defineDisplayColumn', $request, $response);
        $this->assertTrue(isset($response['success']),                  "defineDisplayColumn: success");
        $this->assertTrue(isset($response['success']),                  "defineDisplayColumn: success is set");
    }

    /**
     * @covers API\DatabaseAdmin::copyView
     * @depends testDefineDisplayColumn
     */
    public function testCopyView()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/copyView', $request, $response);
        $this->assertTrue(isset($response['success']),                  "copyView: success is set");
        #$this->assertTrue($response['success'],                         "copyView: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::listViews
     * @depends testCopyView
     */
    public function testListViews()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('GET', '/service/databaseAdmin/listViews', $request, $response);
        $this->assertTrue(isset($response['success']),                  "listViews: success is set");
        #$this->assertTrue($response['success'],                         "listViews: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::getViewInfo
     * @depends testListViews
     */
    public function testGetViewInfo()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('GET', '/service/databaseAdmin/getViewInfo', $request, $response);
        $this->assertTrue(isset($response['success']),                  "getViewInfo: success is set");
        #$this->assertTrue($response['success'],                         "getViewInfo: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::renameView
     * @depends testGetViewInfo
     */
    public function testRenameView()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/renameView', $request, $response);
        $this->assertTrue(isset($response['success']),                  "renameView: success is set");
        #$this->assertTrue($response['success'],                         "renameView: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::dropView
     * @depends testRenameView
     */
    public function testDropView()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/dropView', $request, $response);
        $this->assertTrue(isset($response['success']),                  "dropView: success is set");
        #$this->assertTrue($response['success'],                         "dropView: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::dropTable
     * @depends testDropView
     */
    public function testDropTable()
    {
        $request  = array();
        $response = array();
        $this->_callWebService('POST', '/service/databaseAdmin/dropTable', $request, $response);
        $this->assertTrue(isset($response['success']),                  "dropTable: success is set");
        #$this->assertTrue($response['success'],                         "dropTable: success is true");
    }

    /**
     * @covers API\DatabaseAdmin::dropDatabase
     * @depends testDropTable
     */
    public function testDropDatabase()
    {
        $request  = array();
        $response = array();
        #$this->_callWebService('POST', '/service/databaseAdmin/dropDatabase', $request, $response);
        #$this->assertTrue(isset($response['success']),                  "dropDatabase: success is set");
        #$this->assertTrue($response['success'],                         "dropDatabase: success is true");
    }
}
